<template>
  <!-- @closed="editing=false" 关闭屉式菜单  重置编辑状态为不编辑 -->
  <!--？ Vant动作模板支持 @opne 打开动作模板后触发方法 -->
  <van-action-sheet @open='handleOpen' :value="value" @closed="editing=false" @input="handleClose" title="编辑频道">
    <div class="channel">
      <div class="tit">
        我的频道：
        <span class="tip">点击可进入频道</span>
        <van-button v-if="!editing" @click="editing=true" size="mini" type="info" plain>编辑</van-button>
        <van-button v-else @click="editing=false" size="mini" type="danger" plain>完成</van-button>
      </div>
      <van-grid class="van-hairline--left">
        <van-grid-item v-for="(item,index) in channels" :key="item.id">
          <!-- 添加当前选中频道的高亮类名(用户当前选中的频道 让其高亮显示)
                :class 动态添加高亮类名 类名对象里面三元表达式 判断符合父元素传来的当前索引 让其添加高亮类名 -->
          <!-- ? @click 创建点击事件 携带点击频道的id值(参数) 传给父组件 实现点击后切换到该频道 -->
          <span :class="{red : index === activeindex}" class="f12" @click="enterChannel(index)">{{item.name}}</span>
          <!-- !至少留一个推荐频道(第一个频道 索引为0)
                :show动态隐藏显示 除了索引值为0(推荐频道) 其他都显示删除按钮 -->
          <!-- ~ @click 点击事件 删除频道方法 携带频道id 用于服务器删除 携带索引值 用于页面删除  -->
          <van-icon @click='handleDelete(item.id)' v-show="editing && index!==0" class="btn" name="cross"></van-icon>
        </van-grid-item>
      </van-grid>
    </div>
    <div class="channel">
      <div class="tit">可选频道：</div>
      <van-grid class="van-hairline--left">
        <van-grid-item v-for="items in optionChannels" :key="items.id">

          <span class="f12">{{items.name}}</span>
          <!-- ! @click 点击事件 点击后 添加新的频道数据 携带频道的详细参数 -->
          <van-icon @click="addChannel(items)" class="btn" name="plus"></van-icon>
        </van-grid-item>
      </van-grid>
    </div>
  </van-action-sheet>
</template>
<script>
// ? 导入获取全部频道数据删除频道 添加频道 的api接口
import { getChannels, delChannel, addChannel } from '../api/channel'

export default {
  // 导入父组件传来的数据
  props: {
    // 控制弹窗组件的显示
    value: {
      type: Boolean
    },
    // 我的频道数据
    channels: {
      type: Array,
      // 表示数组的默认值是空数组[]
      default: () => []
    },
    // 当前频道的索引(选中的频道)
    activeindex: {
      type: Number
    }
  },
  data () {
    return {
      // 叉号的显示对象
      editing: false,
      // ? 获取全部频道数据 对象保存
      allChannels: []
    }
  },
  methods: {
    //! 设置添加频道的方法
    //! 因为无法获取后台seq顺号  只能前端排序让后端统一即可。(后端要求 新的频道总列表 添加序号上传后端)
    //! 后端需要 完整的排好序的 数组 [{id,seq},...] 注意：不需要推荐
    //! 本地需要 {id, name} 利用map方法 往里面添加 频道序列号
    addChannel (channel) {
      //! 准备参数：对每一个现有频道进行排序（添加一个seq属性进行编号）；并且去掉【推荐】频道
      //! 先对之前的频道排序 利用map方法(包含index参数) 往里面添加 频道序列号
      const orderChannels = this.channels.map((item, index) => {
        return {
          //! 添加频道数据的id
          id: item.id,
          //! 添加频道数据的名称
          name: item.name,
          //! 添加频道数据的 索引(map自带)
          seq: index
        }
      })
      //! 把点击的新频道 添加到map遍历的数组中 编号seq是map数组的长度
      orderChannels.push({ id: channel.id, name: channel.name, seq: orderChannels.length })
      //! 去除第一个【推荐】频道 splice 方法
      orderChannels.splice(0, 1)
      //! 调用接口 通知服务器 添加频道的操作
      try {
        //! 请求服务器 添加频道列表
        addChannel(orderChannels)
        //! 添加频道成功后，添加页码的频道(传给父组件 通知父组件更新数据)
        //! 因为首页的频道数据有额外的属性值 所以需要添加这些内容 传给父组件
        const newChannel = {
          //! 频道的id
          id: channel.id,
          //! 频道的标签名称
          name: channel.name,
          //! 文章列表加载状态
          loading: false,
          //! 下拉刷新的完成状态
          isLoading: false,
          //! 上拉列表加载完成的标志
          finished: false,
          //! 下拉刷新完成的提示信息
          pullText: '加载成功',
          //! 时间戳，用于实现列表的分页查询
          timestamp: +new Date(),
          //! 文章列表
          articles: []
        }
        //! 把新的频道数据传递给父组件，让父组件去添加到页面上
        this.$emit('addChannel', newChannel)
      } catch (error) {
        //! 通知用户
        this.$toast('添加失败')
      }
    },
    // 与父组件传值 关闭频道编辑窗口
    handleClose () {
      this.$emit('input', false)
    },
    // ? 打开动作模板后执行的方法
    async handleOpen () {
      // ? 调用接口获取所有的频道数据
      // ? 判断 如果获取成功 得到数据 不成功提示用户
      try {
        const ret = await getChannels()
        this.allChannels = ret.data.channels
      } catch (error) {
        // ? 不成功 提示用户
        this.$toast('获取频道列表失败')
      }
    },
    // ? 接收点击频道的id值 创给子组件 实现点击频道后 跳转到该频道
    enterChannel (index) {
      // ? 1、关闭窗口
      this.$emit('input', false)
      // ? 这里需要把index传递给父组件并且给active赋值
      this.$emit('update:activeindex', index)
    },
    // ~ 添加删除频道功能方法
    async handleDelete (id) {
      try {
        // ~ 通知服务器 进行频道删除
        await delChannel(id)
        // ~ 删除成功后 把id值创给父组件 通知父组件在页面上进行删除
        this.$emit('delChannel', id)
      } catch (error) {
        // ~ 提示用户 删除失败
        this.$toast('频道删除失败')
      }
    }
  },
  // ? 添加计算属性
  computed: {
    // ? 添加计算方法 总频道列表 比对 用户已经关注的列表 得出用户还没有关注的频道
    optionChannels () {
      // ? 进行筛选 filter方法进行数据总筛选 接收some() some传来的true为取反 代表不存在的数据为true filter方法储存不存在的数据即可
      // ? filter() 方法创建一个新的数组，新数组中的元素是通过检查指定数组中符合条件的所有元素
      return this.allChannels.filter(item => { // allChannels 是全部频道数据 channels是我的频道数据
        // ? 进行符合条件筛选 some() 并且取反 把不满足条件的取反变成true 返回给filter()筛选器
        // ?  some()方法作用：判断数组中是否包含符合条件的数据，只要有一项符合，就返回true
        return !this.channels.some(items => {
          // ? 比对 filter的数据 返回true
          return items.id === item.id
        })
      })
    }
  }
}
</script>
<style lang="less" scoped>
.van-popup--bottom {
  &.van-popup--round {
    border-radius: 0;
  }
}
.van-action-sheet {
  max-height: 100%;
  height: 100%;
  .van-action-sheet__header {
    background: #3296fa;
    color: #fff;
    .van-icon-close {
      color: #fff;
    }
  }
}
.channel {
  padding: 10px;
  .tit {
    line-height: 3;
    .tip {
      font-size: 10px;
      color: #999;
    }
  }
  .van-button {
    float: right;
    margin-top: 7px;
  }
  .btn {
    position: absolute;
    bottom: 0;
    right: 0;
    background: #ddd;
    font-size: 12px;
    color: #fff;
  }
  .f12 {
    font-size: 12px;
    color: #555;
  }
  .red {
    color: red;
  }
}
</style>
